import { Injectable, NotFoundException } from '@nestjs/common';
import { FileStorageService } from '../shared/file-storage.service';
import { CreateRecipeDto, RecipeFilterDto } from './dto/recipe.dto';
import { DailyRecommendation, MealRecommendation, RecipeType, MealType } from './types/recipe.types';

interface DailyRecommendationCache {
  [key: string]: {
    date: string;
    recommendation: DailyRecommendation;
  };
}

@Injectable()
export class RecipeService {
  private readonly RECIPES_FILE = 'data/recipes.json';
  // 用于缓存可用菜品
  private availableRecipes: {
    [key in MealType]: {
      [key in RecipeType]: any[];
    };
  } = {
    breakfast: { meat: [], vegetable: [], soup: [] },
    lunch: { meat: [], vegetable: [], soup: [] },
    dinner: { meat: [], vegetable: [], soup: [] }
  };

  // 每日推荐缓存
  private dailyRecommendationCache: DailyRecommendationCache = {};

  constructor(private readonly fileStorage: FileStorageService) {}

  async getAllRecipes() {
    const { recipes } = await this.fileStorage.readJsonFile(this.RECIPES_FILE);
    return recipes.map(recipe => ({
      id: recipe.id,
      type: recipe.type,
      name: recipe.name,
      imageUrl: recipe.imageUrl
    }));
  }

  async createRecipe(createRecipeDto: CreateRecipeDto) {
    const { recipes } = await this.fileStorage.readJsonFile(this.RECIPES_FILE);
    const newRecipe = {
      id: Date.now().toString(),
      ...createRecipeDto,
      createdAt: new Date().toISOString(),
    };
    
    recipes.push(newRecipe);
    await this.fileStorage.writeJsonFile(this.RECIPES_FILE, { recipes });
    return newRecipe;
  }

  async updateRecipe(id: string, updateRecipeDto: CreateRecipeDto) {
    const { recipes } = await this.fileStorage.readJsonFile(this.RECIPES_FILE);
    const recipeIndex = recipes.findIndex(recipe => recipe.id === id);
    
    if (recipeIndex === -1) {
      throw new NotFoundException('菜谱不存在');
    }

    // 更新菜谱信息,保留原有的ID和创建时间
    const updatedRecipe = {
      ...recipes[recipeIndex],
      ...updateRecipeDto,
      id, // 保持原有ID
      createdAt: recipes[recipeIndex].createdAt, // 保持原有创建时间
    };

    recipes[recipeIndex] = updatedRecipe;
    await this.fileStorage.writeJsonFile(this.RECIPES_FILE, { recipes });
    return updatedRecipe;
  }

  // 检查是否需要更新缓存
  private shouldUpdateCache(familyId: string): boolean {
    const cache = this.dailyRecommendationCache[familyId];
    if (!cache) return true;

    const today = new Date().toISOString().split('T')[0];
    return cache.date !== today;
  }

  async getDailyRecommendation(filter: RecipeFilterDto, familyId: string): Promise<DailyRecommendation> {
    // 检查缓存
    if (!this.shouldUpdateCache(familyId)) {
      return this.dailyRecommendationCache[familyId].recommendation;
    }

    const { recipes } = await this.fileStorage.readJsonFile(this.RECIPES_FILE);
    
    // 根据家庭偏好筛选菜谱
    const filteredRecipes = recipes.filter(recipe => {
      return (
        (!filter.spicy || recipe.spicyLevel <= filter.spicyLevel) &&
        (!filter.allergies || !filter.allergies.some(allergy => 
          recipe.ingredients.includes(allergy)
        ))
      );
    });

    // 按餐次和类型分类菜品
    const categorizedRecipes = {
      breakfast: {
        meat: filteredRecipes.filter(r => r.mealTypes.includes('breakfast') && r.type === 'meat'),
        vegetable: filteredRecipes.filter(r => r.mealTypes.includes('breakfast') && r.type === 'vegetable'),
        soup: filteredRecipes.filter(r => r.mealTypes.includes('breakfast') && r.type === 'soup')
      },
      lunch: {
        meat: filteredRecipes.filter(r => r.mealTypes.includes('lunch') && r.type === 'meat'),
        vegetable: filteredRecipes.filter(r => r.mealTypes.includes('lunch') && r.type === 'vegetable'),
        soup: filteredRecipes.filter(r => r.mealTypes.includes('lunch') && r.type === 'soup')
      },
      dinner: {
        meat: filteredRecipes.filter(r => r.mealTypes.includes('dinner') && r.type === 'meat'),
        vegetable: filteredRecipes.filter(r => r.mealTypes.includes('dinner') && r.type === 'vegetable'),
        soup: filteredRecipes.filter(r => r.mealTypes.includes('dinner') && r.type === 'soup')
      }
    };

    // 为每个餐次随机选择一荤一素一汤
    const recommendation: DailyRecommendation = {
      breakfast: {
        meat: this.selectRandomRecipe(categorizedRecipes.breakfast.meat),
        vegetable: this.selectRandomRecipe(categorizedRecipes.breakfast.vegetable),
        soup: this.selectRandomRecipe(categorizedRecipes.breakfast.soup)
      },
      lunch: {
        meat: this.selectRandomRecipe(categorizedRecipes.lunch.meat),
        vegetable: this.selectRandomRecipe(categorizedRecipes.lunch.vegetable),
        soup: this.selectRandomRecipe(categorizedRecipes.lunch.soup)
      },
      dinner: {
        meat: this.selectRandomRecipe(categorizedRecipes.dinner.meat),
        vegetable: this.selectRandomRecipe(categorizedRecipes.dinner.vegetable),
        soup: this.selectRandomRecipe(categorizedRecipes.dinner.soup)
      }
    };

    // 更新缓存
    this.dailyRecommendationCache[familyId] = {
      date: new Date().toISOString().split('T')[0],
      recommendation
    };

    return recommendation;
  }

  async getRecipeById(id: string) {
    const { recipes } = await this.fileStorage.readJsonFile(this.RECIPES_FILE);
    const recipe = recipes.find(recipe => recipe.id === id);
    
    if (!recipe) {
      throw new NotFoundException('菜谱不存在');
    }
    
    return recipe;
  }

  // 初始化可用菜品缓存
  private initializeAvailableRecipes(recipes: any[]) {
    // 重置缓存
    this.availableRecipes = {
      breakfast: { meat: [], vegetable: [], soup: [] },
      lunch: { meat: [], vegetable: [], soup: [] },
      dinner: { meat: [], vegetable: [], soup: [] }
    };

    // 按餐次和类型分类菜品
    for (const recipe of recipes) {
      for (const mealType of recipe.mealTypes) {
        if (this.availableRecipes[mealType]) {
          this.availableRecipes[mealType][recipe.type].push(recipe);
        }
      }
    }
  }

  // 从可用菜品中随机选择一个并移除
  private async selectAndRemoveRecipe(mealType: MealType, type: RecipeType): Promise<any> {
    const recipes = this.availableRecipes[mealType][type];
    if (!recipes.length) {
      // 如果没有可用菜品，重新加载全部菜品
      const { recipes: allRecipes } = await this.fileStorage.readJsonFile(this.RECIPES_FILE);
      this.initializeAvailableRecipes(allRecipes);
      return this.selectAndRemoveRecipe(mealType, type);
    }

    // 随机选择一个菜品并从可用列表中移除
    const index = Math.floor(Math.random() * recipes.length);
    return recipes.splice(index, 1)[0];
  }

  async generateWeeklyPlan(familyId: string) {
    const { recipes } = await this.fileStorage.readJsonFile(this.RECIPES_FILE);
    
    // 初始化可用菜品缓存
    this.initializeAvailableRecipes(recipes);
    
    const weeklyPlan = [];
    
    // 生成七天的菜单
    for (let i = 0; i < 7; i++) {
      const mealPlan = {
        day: i + 1,
        meals: {
          breakfast: {
            meat: await this.selectAndRemoveRecipe('breakfast', 'meat'),
            vegetable: await this.selectAndRemoveRecipe('breakfast', 'vegetable'),
            soup: await this.selectAndRemoveRecipe('breakfast', 'soup')
          },
          lunch: {
            meat: await this.selectAndRemoveRecipe('lunch', 'meat'),
            vegetable: await this.selectAndRemoveRecipe('lunch', 'vegetable'),
            soup: await this.selectAndRemoveRecipe('lunch', 'soup')
          },
          dinner: {
            meat: await this.selectAndRemoveRecipe('dinner', 'meat'),
            vegetable: await this.selectAndRemoveRecipe('dinner', 'vegetable'),
            soup: await this.selectAndRemoveRecipe('dinner', 'soup')
          }
        }
      };
      weeklyPlan.push(mealPlan);
    }

    return weeklyPlan;
  }

  private selectRandomRecipe(recipes: any[]) {
    if (!recipes.length) return null;
    return recipes[Math.floor(Math.random() * recipes.length)];
  }
}